import pino from 'pino';
import { Logger } from '@/types';

/**
 * Logger implementation using Pino
 */
export class PinoLogger implements Logger {
  private readonly logger: pino.Logger;

  constructor(name: string, options: pino.LoggerOptions = {}) {
    this.logger = pino({
      name,
      level: process.env.LOG_LEVEL || 'info',
      ...options,
    });
  }

  debug(message: string, meta?: Record<string, unknown>): void {
    this.logger.debug(meta, message);
  }

  info(message: string, meta?: Record<string, unknown>): void {
    this.logger.info(meta, message);
  }

  warn(message: string, meta?: Record<string, unknown>): void {
    this.logger.warn(meta, message);
  }

  error(message: string, error?: Error, meta?: Record<string, unknown>): void {
    const errorMeta = error ? { error: error.message, stack: error.stack } : {};
    this.logger.error({ ...errorMeta, ...meta }, message);
  }
}

/**
 * Console logger implementation for development
 */
export class ConsoleLogger implements Logger {
  constructor(private readonly name: string) {}

  debug(message: string, meta?: Record<string, unknown>): void {
    console.debug(`[${this.name}] DEBUG: ${message}`, meta || '');
  }

  info(message: string, meta?: Record<string, unknown>): void {
    console.info(`[${this.name}] INFO: ${message}`, meta || '');
  }

  warn(message: string, meta?: Record<string, unknown>): void {
    console.warn(`[${this.name}] WARN: ${message}`, meta || '');
  }

  error(message: string, error?: Error, meta?: Record<string, unknown>): void {
    console.error(`[${this.name}] ERROR: ${message}`, error || '', meta || '');
  }
}

/**
 * Silent logger implementation for testing
 */
export class SilentLogger implements Logger {
  debug(): void {
    // Silent
  }

  info(): void {
    // Silent
  }

  warn(): void {
    // Silent
  }

  error(): void {
    // Silent
  }
}

/**
 * Logger factory
 */
export class LoggerFactory {
  private static defaultLoggerType: 'pino' | 'console' | 'silent' = 'pino';

  static setDefaultType(type: 'pino' | 'console' | 'silent'): void {
    this.defaultLoggerType = type;
  }

  static create(name: string, type?: 'pino' | 'console' | 'silent'): Logger {
    const loggerType = type || this.defaultLoggerType;

    switch (loggerType) {
      case 'pino':
        return new PinoLogger(name);
      case 'console':
        return new ConsoleLogger(name);
      case 'silent':
        return new SilentLogger();
      default:
        throw new Error(`Unknown logger type: ${loggerType}`);
    }
  }
}

// Default logger creation function
export const createLogger = (name: string): Logger => {
  return LoggerFactory.create(name);
};

// Global logger instance
export const globalLogger = createLogger('RabbitMQ');

// Export all utilities
export * from './retry';
export * from './validation';
export * from './routing';
